package implementation1.app;

import exceptions.CommandNotFoundException;
import exceptions.CreatingProcessException;
import implementation1.data.Account;
import implementation1.data.Handle;
import interfaces.app.IProcess;
import interfaces.app.IProcessCreator;
import interfaces.data.IHandle;

import java.lang.reflect.Constructor;
import java.util.ResourceBundle;

/**
 * Creates processes for creating processes.
 * Created: 15.10.11
 *
 * @author Jan Svab
 */
public class ProcessCreator implements IProcessCreator
{
    /**
     * Create new process.
     *
     * @param parent the parent process of a new process
     * @param handle a handle of process
     * @return the new process
     * @throws CreatingProcessException Thrown if failed creating process.
     * @throws CommandNotFoundException Inherited from CreatingProcessException. Thrown if class for command wasn't found.
     */
    @Override
    public IProcess createProcess(IProcess parent, IHandle handle) throws CreatingProcessException
    {
        ResourceBundle bundle = ResourceBundle.getBundle("implementation1.res.messages");

        String commandName = handle.getCommandName();
        if (handle.getCommandName() != null && handle.getCommandName().length() != 0)
        {
            commandName = commandName.substring(0, 1).toUpperCase() + commandName.substring(1);
        }

        Class<?> commandClass = null;
        try
        {
            commandClass = Class.forName("implementation1.app.commands." + commandName);
        } catch (ClassNotFoundException e)
        {
            throw new CommandNotFoundException("'" + handle.getCommandName() + "' " + bundle.getString("error.commandNotFound"));
        }

        Constructor constructorOfCommand = null;
        try
        {
            constructorOfCommand = commandClass.getConstructor(IProcess.class, IHandle.class);
        } catch (NoSuchMethodException e)
        {
            throw new CreatingProcessException(bundle.getString("error.commandHasWrongConstructor"));
        }

        if (constructorOfCommand == null)
        {
            throw new CreatingProcessException(bundle.getString("error.commandHasNoConstructor"));
        }
        try
        {
            return (IProcess) constructorOfCommand.newInstance(parent, handle);

        } catch (Exception e)
        {
            throw new CreatingProcessException(bundle.getString("error.failCreateProcess"));
        }
    }

    /**
     * Create new root process, parent of new process is null. Must set actual path in handle according to username.
     *
     * @return the new process
     * @throws CreatingProcessException Thrown if failed creating process.
     * @throws CommandNotFoundException Inherited from CreatingProcessException. Thrown if class for command wasn't found.
     */
    @Override
    public IProcess createRootProcess() throws CreatingProcessException
    {
        IHandle handle = new Handle(null, null, null, null, "init", "C:\\", new Account("everyone", "", Account.NO_USER));

        return new InitProcess(handle);
    }
}
